package mop.model.task.field;

import mop.exception.IllegalDescriptionException;
import mop.exception.IllegalIdException;
import mop.exception.IllegalValueException;
/**
 * Field Class 
 * 
 * @author MOP Team 7
 * 
 * @invar 	Id is valid.
 *  		| isValidId(getId())
 *  
 * @invar 	Description is valid.
 *  		| isValidDescription(getDescription())
 *    
 */

public abstract class Field implements FieldInterface
{
	/**
	 * Basic Constructor for Field Class
	 * 
	 * @param id			Identifier for field
	 * @param description	Description for field
	 * 
	 * @post id is set to given identifier
	 * 	this.getId() == id
	 * @post description is set to given description
	 * 	this.getDescription() == description
	 * 
	 * @throws IllegalIdException
	 * @throws IllegalDescriptionException
	 */
	public Field(String id, String description) throws IllegalIdException, IllegalDescriptionException
	{
		if(!isValidId(id))
			throw new IllegalIdException(id);
		else
			this.id = id;
		
		if(!isValidDescription(description))
			throw new IllegalDescriptionException(description);
		else
			this.description = description;
		
	}

	/**
	 * Check whether given object is same as this object
	 * Yes, we use instanceof (NOOOOOOOOOOOOOOO!), but otherwise madame Lizkov would complain.
	 * 
	 * @return true if two objects have the same description and id
	 */
        @Override
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Field))
			throw new IllegalArgumentException("Given object must implement modelinterface");
		
		return (this.toString().equals(obj.toString())) && (this.getId().equals(((Field) obj).getId())) ;
		
	}

	/**
	 * Copy / Clone
	 * 
	 * @param field the field entity
	 * 
	 * @return a clone of the current field
	 */
	public abstract Field clone(); 
	
	/***************************************************************************
	 * 						Value
	 ***************************************************************************/
	
	/**
	 * This is were the magic happens reimplement this
	 * function to check if the passed string fits you're specifications
	 * 
	 * @param value the value in string form
	 * 
	 * @throws IllegalValue Exception
	 * 	when the passed string does not meet the subclasses standards
	 */
	public abstract void setValue(String value) throws IllegalValueException;
	
	/**
	 * return the current value in String form to be used by our lovely UI
	 * every class must reimplement this for himself as the value will 
	 * probably need a reformat of some sort
	 * @return String value
	 */
	public abstract String getValue();
	
	
	/***************************************************************************
	 * 						Model interface
	 ***************************************************************************/
	
	/**
	 * @see FieldInterface#getId()
	 */
	public String getId() 
	{
		return id;
	}
	
	/**
	 * Check whether given identifier is valid
	 * @param id	Identifier to check
	 * @return true if valid, false otherwise
	 */
	public static boolean isValidId(String id) {
		return (id != null && (!(id.trim().equals(""))));
	}
	
	/**
	 * Identifier for this field
	 */
	private final String id;
	
	/**
	 * @see FieldInterface#getDescription()
	 */
	public String getDescription() 
	{
		return description;
	}
	
	/**
	 * Check whether given description is valid
	 * @param description	Description to check
	 * @return true if valid, false otherwise
	 */
	public static boolean isValidDescription(String description) {
		return (description != null && (!(description.trim().equals(""))));
	}
	
	/**
	 * Description for this field
	 */
	private final String description;
	
	/**
	 * get a reference to the interface
	 * @return this
	 */
	public FieldInterface getInterface()
	{
		return this;
	}
}
